package com.liang.bishi.nj;

/**
 * 领悦南京 10.30
 * 第一题：实现单例模式
 */
public class Problem01 {
    public static void main(String[] args) {

    }
}


/**
 * 1.饿汉式
 */
class SingletonEager {

    // 2.定义私有静态的单例对象
    private static final SingletonEager instance = new SingletonEager();

    // 1.构造方法私有，避免外部随意 new 对象
    private SingletonEager() {
    }

    // 3.对外提供一个访问该单例的全局访问点
    public static SingletonEager getInstance() {
        return instance;
    }
}

/**
 * 2.懒汉式
 */
class SingletonLazy {
    private static SingletonLazy instance;

    private SingletonLazy() {
    }

    public static SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

/**
 * 3.线程安全的懒汉式单例
 */
class SingletonSynchronized {
    private static SingletonSynchronized instance;

    private SingletonSynchronized() {
    }

    public static synchronized SingletonSynchronized getInstance() {
        if (instance == null) {
            instance = new SingletonSynchronized();
        }
        return instance;
    }
}

/**
 * 4.双重检查锁
 * 线程安全的懒汉式改进
 * 优点：线程安全，效率高
 */
class SingletonDoubleChecked {
    // volatile 防止指令重排
    private static volatile SingletonDoubleChecked instance;

    private SingletonDoubleChecked() {
    }

    public static SingletonDoubleChecked getInstance() {
        // 提高效率
        if (instance == null) {
            // 保证线程安全
            synchronized (SingletonDoubleChecked.class) {
                if (instance == null) {
                    // 不是原子操作，包括：
                    // 1.分配对象内存空间 memory=allocate()
                    // 2.初始化对象 ctorInstance(memory)
                    // 3.instance 指向创建的对象地址 instance=memory
                    instance = new SingletonDoubleChecked();
                }
            }
        }
        return instance;
    }
}

/**
 * 5.静态内部类方式
 * 改进了饿汉式，线程安全，实现了延迟加载
 */
class SingletonInnerClass {
    private SingletonInnerClass() {
    }

    // 静态内部类：不会随着外部类的加载和初始化而初始化，使用时才会加载和初始化
    private static class Inner {
        private static final SingletonInnerClass INSTANCE = new SingletonInnerClass();
    }

    public static SingletonInnerClass getInstance() {
        return Inner.INSTANCE;
    }
}

/**
 * 6.枚举方式
 * 线程安全，最安全的方式
 * 枚举不会被反射、序列化破坏单例
 */
enum SingletonEnum {
    INSTANCE;

    public void doSomething() {
        System.out.println("Do something...");
    }
}
